﻿using NuMvvm.Helpers;
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace NuMvvm
{
    /// <summary>
    /// Gives access to some useful properties of the current application.
    /// </summary>
    public static class DesignProperties
    {
        // Contains code and logic from GalaSoft MVVM Light.

        private static bool? _isInDesignMode;

        #region Design-Mode Detection 

        ///// <summary>
        ///// Gets a value indicating whether the control is in design mode
        ///// (running under Blend or Visual Studio).
        ///// </summary>
        //[SuppressMessage(
        //    "Microsoft.Performance",
        //    "CA1822:MarkMembersAsStatic",
        //    Justification = "Non static member needed for data binding")]
        //public bool IsInDesignMode
        //{
        //    get
        //    {
        //        return IsInDesignModeStatic;
        //    }
        //}

        /// <summary>
        /// Gets a value indicating whether the control is in design mode
        /// (running in Blend or Visual Studio).
        /// </summary>
        [SuppressMessage(
            "Microsoft.Security",
            "CA2122:DoNotIndirectlyExposeMethodsWithLinkDemands",
            Justification = "The security risk here is neglectible.")]
        public static bool IsInDesignMode
        {
            get
            {
                if (!_isInDesignMode.HasValue)
                {
                    _isInDesignMode = IsInDesignModePortable();
                }

                return _isInDesignMode.Value;
            }
        }

        private static bool IsInDesignModePortable()
        {
            // As a portable lib, we need see what framework we're runnign on
            // and use reflection to get the designer value

            var platform = DesignerLibrary.DetectedDesignerLibrary;

            if (platform == DesignerPlatformLibrary.WinRt)
                return IsInDesignModeMetro();

            if (platform == DesignerPlatformLibrary.Silverlight)
            {
                var desMode = IsInDesignModeSilverlight();
                if (!desMode)
                    desMode = IsInDesignModeNet(); // hard to tell these apart in the designer

                return desMode;
            }

            if (platform == DesignerPlatformLibrary.Net)
                return IsInDesignModeNet();

            return false;
        }



        private static bool IsInDesignModeSilverlight()
        {
            try
            {
                var dm = Type.GetType("System.ComponentModel.DesignerProperties, System.Windows, Version=2.0.5.0, Culture=neutral, PublicKeyToken=7cec85d7bea7798e");

                var dme = dm.GetTypeInfo().GetDeclaredProperty("IsInDesignTool");
                return (bool)dme.GetValue(null, null);
            }
            catch
            {
                return false;
            }
        }

        private static bool IsInDesignModeMetro()
        {
            try
            {
                var dm = Type.GetType("Windows.ApplicationModel.DesignMode, Windows, ContentType=WindowsRuntime");

                var dme = dm.GetTypeInfo().GetDeclaredProperty("DesignModeEnabled");
                return (bool)dme.GetValue(null, null);
            }
            catch
            {
                return false;
            }
        }

        private static bool IsInDesignModeNet()
        {
            try
            {
                var dm =
                    Type.GetType(
                        "System.ComponentModel.DesignerProperties, PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");


                var dmp = dm.GetTypeInfo().GetDeclaredField("IsInDesignModeProperty").GetValue(null);

                var dpd =
                    Type.GetType(
                        "System.ComponentModel.DependencyPropertyDescriptor, WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");
                var typeFe =
                    Type.GetType("System.Windows.FrameworkElement, PresentationFramework, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");


                var fromPropertys = dpd
                    .GetTypeInfo()
                    .GetDeclaredMethods("FromProperty");

                var fromProperty = fromPropertys
                    .FirstOrDefault(mi => mi.IsPublic && mi.IsStatic && mi.GetParameters().Length == 2);

                if (fromProperty == null)
                {
                    return false;
                }

                var descriptor = fromProperty.Invoke(null, new[] { dmp, typeFe });

                var metaProp = dpd.GetTypeInfo().GetDeclaredProperty("Metadata");

                var metadata = metaProp.GetValue(descriptor, null);

                var tPropMeta = Type.GetType("System.Windows.PropertyMetadata, WindowsBase, Version=3.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35");

                var dvProp = tPropMeta.GetTypeInfo().GetDeclaredProperty("DefaultValue");

                var dv = (bool)dvProp.GetValue(metadata, null);
                return dv;
            }
            catch
            {
                return false;
            }
        }

        #endregion
    }
}
